Skip to content

♻️ Migrate Storybook & Static-Site SDKs from Puppeteer to Playwright#193

Merged
Robdel12 merged 13 commits into
mainfrom
feat/storybook-client-side-navigation
Jan 30, 2026
Merged

♻️ Migrate Storybook & Static-Site SDKs from Puppeteer to Playwright#193
Robdel12 merged 13 commits into
mainfrom
feat/storybook-client-side-navigation

Conversation

@Robdel12
Copy link
Copy Markdown
Contributor

@Robdel12 Robdel12 commented Jan 29, 2026

Summary

This PR fixes critical screenshot timeout issues in CI and dramatically improves performance by migrating both the Storybook and Static-Site SDKs from Puppeteer to Playwright.

Root cause: Puppeteer's new headless mode has known issues with parallel screenshot capture causing timeouts. Playwright's BrowserContext provides proper isolation for parallel workers.

Results:

  • Screenshots now complete in <1 second instead of timing out after 60+ seconds
  • Client-side navigation for Storybook provides ~47x speedup (94s → 2s for 10 screenshots)

Changes

Puppeteer → Playwright Migration

  • Replace puppeteer with playwright-core in both SDKs
  • Migrate from tab-based pooling to BrowserContext-based pooling for proper isolation
  • Update API calls: setViewport()setViewportSize(), networkidle2networkidle
  • Fix page.evaluate() syntax: Playwright uses object destructuring ({ args }) => {}, { args }

Chrome Browser Flags Audit

  • Remove deprecated flags causing hangs (--disable-gpu + --disable-software-rasterizer)
  • Remove flags deprecated since 2017-2019 (--disable-translate, --safebrowsing-disable-auto-update)
  • Use modern --disable-features=Translate,OptimizationHints,MediaRouter approach
  • Add screenshot consistency flags (--force-color-profile=srgb, --hide-scrollbars)
  • Document flags in docs/browser-flags.md with source of truth references

Storybook Client-Side Navigation

  • Use __STORYBOOK_PREVIEW__.channel.emit('setCurrentStory') instead of full page reloads
  • First story per tab: Full page load to initialize Storybook
  • Subsequent stories: Client-side navigation + wait for storyRendered event
  • Sort tasks by viewport to minimize resize operations

Plugin System Enhancement

  • Support vizzlyPlugin field in package.json for plugin registration

CI Improvements

  • Update E2E workflow for Playwright browser installation
  • Restructure SDK E2E tests to match real user workflow
  • Add proper build steps before E2E tests

Test plan

  • All unit tests pass
  • Storybook E2E: 5 screenshots in 0s (TDD mode)
  • Storybook E2E: 5 screenshots in 0s (Cloud mode) - previously ALL timed out
  • Static-Site E2E: 5 screenshots in 1s (TDD mode)
  • Static-Site E2E: Works (Cloud mode) - previously slow/timing out
  • CI passes for all SDK E2E jobs

Instead of doing full page.goto() for each story (which reloads the
entire Storybook bundle), we now:

1. First story per tab: Full page load to initialize Storybook
2. Subsequent stories: Client-side navigation via __STORYBOOK_PREVIEW__

Performance improvement: ~47x faster (94s → 2s for 10 screenshots)

Changes:
- Add navigation.js with smart client-side routing
- Sort tasks by viewport to minimize resize operations
- Skip resetTab() to keep Storybook context loaded
- Update task structure to use storyId/baseUrl instead of url
- Fix example-storybook: add vite.config.js with React plugin
@vizzly-testing

This comment has been minimized.

@claude
Copy link
Copy Markdown

claude Bot commented Jan 29, 2026

Code Review: Client-Side Navigation for Storybook Screenshots

Summary

Excellent performance optimization achieving 47x speedup (94s → 2s). Well-architected with comprehensive test coverage and thoughtful error handling.

Key Strengths

  • Smart navigation strategy with first-visit/subsequent-visit pattern
  • Clean separation of concerns in new navigation.js module
  • Viewport sorting optimization to minimize resize operations
  • 177 new test lines covering all major paths
  • Clear documentation with JSDoc explaining design rationale

Critical Issues

1. Memory Leak: Event Listener Cleanup (MUST FIX)

Location: navigation.js:107-122

If storyRendered event fires before timeout, the timeout is NOT cleared. This creates timer leaks.

Fix: Add clearTimeout when event handler fires:

let timeoutId;
let handleRendered = () => {
  clearTimeout(timeoutId);
  preview.channel.off('storyRendered', handleRendered);
  resolve();
};
timeoutId = setTimeout(() => { /* ... */ }, timeout);

2. Hard-coded Timeout (SHOULD FIX)

Location: navigation.js:118-122

5-second timeout is hard-coded, ignoring the configurable timeout parameter. Use the passed timeout instead of 5000ms.

3. Silent Error Swallowing (SHOULD FIX)

Location: navigation.js:49-56

Catch block silently swallows errors. Add debug logging before fallback.

Minor Issues

  • Package-lock includes unrelated Babel updates (consider separate PR)
  • Test coverage missing: API exists but setCurrentStory throws
  • Viewport sort test could verify deterministic order

Security & Performance

  • ✅ No security issues - storyId properly encoded
  • ✅ 47x performance improvement well-validated
  • ✅ Excellent test coverage

Verdict

Approve with changes

Outstanding work with significant performance gains. Fix the timer leak (#1) and hard-coded timeout (#2) before merge. Once addressed, ready to ship.

Performance: 🚀 47x faster | Quality: 📝 Well-tested | Risk: 🟢 Low

Add backwards-compatible support for new `vizzlyPlugin` package.json
field alongside legacy `vizzly.plugin`. This fixes cosmiconfig conflict
where `vizzly` field was being read as config instead of plugin marker.

- Plugin loader now checks `vizzlyPlugin` first, falls back to `vizzly.plugin`
- Existing plugins continue to work unchanged
E2E tests now run the actual CLI commands like users would:
- Storybook: `vizzly storybook ./example-storybook/dist`
- Static-site: `vizzly static-site ../../test-site`

Old SDK integration tests renamed to sdk-integration.test.js
and moved to separate test:sdk-integration script.

Added .vizzlyrc.js for local dev plugin loading, and updated
both plugins to use new vizzlyPlugin field.
- Use Puppeteer browser caching instead of Playwright (both plugins use Puppeteer)
- Add example-storybook build step before running E2E tests
Code review fixes:
- Clear timeout when storyRendered event fires (prevents timer leak)
- Use configurable timeout parameter instead of hardcoded 5000ms
- Add debug logging before falling back to full page navigation
@vizzly-testing

This comment has been minimized.

@vizzly-testing

This comment has been minimized.

1 similar comment
@vizzly-testing

This comment has been minimized.

The .vizzlyrc.js config loads plugins from ./dist/plugin.js,
which requires building the client first.
@vizzly-testing
Copy link
Copy Markdown

Vizzly - Visual Test Results

CLI Reporter - 6 changes need review
Status Count
Passed 13
Changed 6
Auto-approved 13
Changes needing review (6)

filter-failed-only · Firefox · 1920×1080 · 1.3% diff

filter-failed-only

bulk-accept-dialog · Firefox · 1920×1080 · 9.8% diff

bulk-accept-dialog

fullscreen-viewer · Firefox · 1920×1080 · 0.1% diff

fullscreen-viewer

viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff

viewer-zoomed-100

fullscreen-viewer · Firefox · 375×667 · 79.9% diff

fullscreen-viewer

bulk-accept-dialog · Firefox · 375×667 · 159.2% diff

bulk-accept-dialog

Review changes

CLI TUI - Processing...

Build in progress...


feat/storybook-client-side-navigation · b4d72d6c

@vizzly-testing
Copy link
Copy Markdown

Vizzly - Visual Test Results

CLI Reporter - 6 changes need review
Status Count
Passed 13
Changed 6
Auto-approved 13
Changes needing review (6)

filter-failed-only · Firefox · 1920×1080 · 1.3% diff

filter-failed-only

bulk-accept-dialog · Firefox · 1920×1080 · 9.8% diff

bulk-accept-dialog

fullscreen-viewer · Firefox · 1920×1080 · 0.1% diff

fullscreen-viewer

viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff

viewer-zoomed-100

fullscreen-viewer · Firefox · 375×667 · 79.9% diff

fullscreen-viewer

bulk-accept-dialog · Firefox · 375×667 · 159.2% diff

bulk-accept-dialog

Review changes

CLI TUI - 1 change needs review
Status Count
Changed 1
Auto-approved 4
Changes needing review (1)

vizzly-help · 1202×1430 · 7.2% diff

vizzly-help

Review changes


feat/storybook-client-side-navigation · b4d72d6c

Adds detailed timing breakdowns when VIZZLY_LOG_LEVEL=debug:
- Navigation: mode selection and duration for each story
- Task steps: viewport, navigate, hook, screenshot timing
- Screenshot: capture vs send timing breakdown
- Client SDK: HTTP call duration
- Server handlers: request received/returned timing

Enabled verbose logging in CI for Storybook E2E tests.
@vizzly-testing
Copy link
Copy Markdown

vizzly-testing Bot commented Jan 29, 2026

Vizzly - Visual Test Results

CLI Reporter - 6 changes need review
Status Count
Passed 13
Changed 6
Auto-approved 13
Changes needing review (6)

filter-failed-only · Firefox · 1920×1080 · 1.3% diff

filter-failed-only

fullscreen-viewer · Firefox · 1920×1080 · 0.1% diff

fullscreen-viewer

bulk-accept-dialog · Firefox · 1920×1080 · 10.4% diff

bulk-accept-dialog

viewer-overlay-mode · Firefox · 1920×1080 · 0.7% diff

viewer-overlay-mode

viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff

viewer-zoomed-100

bulk-accept-dialog · Firefox · 375×667 · 159.2% diff

bulk-accept-dialog

Review changes

CLI TUI - 1 change needs review
Status Count
Changed 1
Auto-approved 4
Changes needing review (1)

vizzly-help · 1202×1430 · 7.2% diff

vizzly-help

Review changes


feat/storybook-client-side-navigation · cfdbbbf3

- Add 45s timeout to screenshot capture to fail fast on hangs
- Auto-detect concurrency from CPU cores (half cores, min 2, max 8)
- Aligns with static-site SDK behavior
@vizzly-testing
Copy link
Copy Markdown

vizzly-testing Bot commented Jan 29, 2026

Vizzly - Visual Test Results

CLI Reporter - 7 changes need review
Status Count
Passed 12
Changed 7
Auto-approved 12
Changes needing review (7)

viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff

viewer-zoomed-100

fullscreen-viewer · Firefox · 1920×1080 · 1.6% diff

fullscreen-viewer

fullscreen-viewer · Firefox · 375×667 · 167.4% diff

fullscreen-viewer

viewer-slide-mode · Firefox · 1920×1080 · 0.6% diff

viewer-slide-mode

viewer-toggle-mode · Firefox · 1920×1080 · 0.1% diff

viewer-toggle-mode

bulk-accept-dialog · Firefox · 375×667 · 159.0% diff

bulk-accept-dialog

...and 1 more in Vizzly.

Review changes

CLI TUI - 1 change needs review
Status Count
Changed 1
Auto-approved 4
Changes needing review (1)

vizzly-help · 1202×1430 · 7.2% diff

vizzly-help

Review changes


feat/storybook-client-side-navigation · 8424c405

- Remove --disable-gpu (not needed since 2021)
- Remove --disable-software-rasterizer (caused hangs with disable-gpu)
- Remove --disable-translate (removed April 2017)
- Remove --safebrowsing-disable-auto-update (removed Nov 2017)
- Add --disable-features=Translate,OptimizationHints,MediaRouter
- Add --hide-scrollbars, --mute-audio, --force-color-profile=srgb
- Add docs/browser-flags.md documenting all flags and source of truth
@vizzly-testing
Copy link
Copy Markdown

vizzly-testing Bot commented Jan 30, 2026

Vizzly - Visual Test Results

CLI Reporter - 6 changes need review
Status Count
Passed 13
Changed 6
Auto-approved 13
Changes needing review (6)

fullscreen-viewer · Firefox · 375×667 · 10.3% diff

fullscreen-viewer

filter-failed-only · Firefox · 1920×1080 · 1.3% diff

filter-failed-only

bulk-accept-dialog · Firefox · 1920×1080 · 10.3% diff

bulk-accept-dialog

viewer-slide-mode · Firefox · 1920×1080 · 0.5% diff

viewer-slide-mode

viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff

viewer-zoomed-100

bulk-accept-dialog · Firefox · 375×892 · 95.5% diff

bulk-accept-dialog

Review changes

CLI TUI - 1 change needs review
Status Count
Changed 1
Auto-approved 4
Changes needing review (1)

vizzly-help · 1202×1430 · 7.2% diff

vizzly-help

Review changes


feat/storybook-client-side-navigation · 154109ac

Puppeteer's new headless mode has known issues with parallel
screenshot capture causing timeouts. Playwright is designed for
automation and handles parallel contexts properly.

Changes:
- Replace puppeteer with playwright-core
- Use BrowserContext for isolation instead of tabs
- Update page.evaluate() syntax for Playwright
- Use page.setViewportSize() instead of page.setViewport()
- Use waitUntil: 'networkidle' instead of 'networkidle2'
- Update CI workflow to install Playwright browsers
@vizzly-testing
Copy link
Copy Markdown

vizzly-testing Bot commented Jan 30, 2026

Vizzly - Visual Test Results

CLI Reporter - 6 changes need review
Status Count
Passed 13
Changed 6
Auto-approved 13
Changes needing review (6)

filter-failed-only · Firefox · 1920×1080 · 1.3% diff

filter-failed-only

fullscreen-viewer · Firefox · 1920×1080 · 0.1% diff

fullscreen-viewer

bulk-accept-dialog · Firefox · 1920×1080 · 6.8% diff

bulk-accept-dialog

viewer-zoomed-100 · Firefox · 1920×1080 · 0.2% diff

viewer-zoomed-100

fullscreen-viewer · Firefox · 375×667 · 198.0% diff

fullscreen-viewer

bulk-accept-dialog · Firefox · 375×667 · 159.1% diff

bulk-accept-dialog

Review changes

CLI TUI - 1 change needs review
Status Count
Changed 1
Auto-approved 4
Changes needing review (1)

vizzly-help · 1202×1430 · 7.2% diff

vizzly-help

Review changes


feat/storybook-client-side-navigation · 621079c3

Same migration as Storybook SDK for consistency and performance.
Screenshots now complete in ~1s instead of 2+ minutes.

Changes:
- Replace puppeteer with playwright-core
- Use BrowserContext for isolation instead of CDP sessions
- Use page.setViewportSize() instead of page.setViewport()
- Update CI workflow to install Playwright browsers
@vizzly-testing
Copy link
Copy Markdown

vizzly-testing Bot commented Jan 30, 2026

Vizzly - Visual Test Results

CLI Reporter - 6 changes need review
Status Count
Passed 13
Changed 6
Auto-approved 13
Changes needing review (6)

fullscreen-viewer · Firefox · 375×667 · 78.6% diff

fullscreen-viewer

bulk-accept-dialog · Firefox · 1920×1080 · 6.8% diff

bulk-accept-dialog

viewer-zoomed-100 · Firefox · 1920×1080 · 0.4% diff

viewer-zoomed-100

fullscreen-viewer · Firefox · 1920×1080 · 1.4% diff

fullscreen-viewer

viewer-overlay-mode · Firefox · 1920×1080 · 5.9% diff

viewer-overlay-mode

viewer-toggle-mode · Firefox · 1920×1080 · 0.1% diff

viewer-toggle-mode

Review changes

CLI TUI - 1 change needs review
Status Count
Changed 1
Auto-approved 4
Changes needing review (1)

vizzly-help · 1202×1430 · 7.2% diff

vizzly-help

Review changes


feat/storybook-client-side-navigation · 25d0300b

@Robdel12 Robdel12 changed the title ⚡ Use client-side navigation for Storybook screenshots ♻️ Migrate Storybook & Static-Site SDKs from Puppeteer to Playwright Jan 30, 2026
- Update pool tests to use BrowserContext mocks (newContext instead of newPage)
- Update viewport tests to use setViewportSize (Playwright API)
- Update navigation tests to use networkidle (not networkidle2)
- Update screenshot tests to include timeout parameter
- Fix lint formatting issues
@vizzly-testing
Copy link
Copy Markdown

vizzly-testing Bot commented Jan 30, 2026

Vizzly - Visual Test Results

CLI Reporter - Approved

19 comparisons approved.

Review changes

CLI TUI - Approved

5 comparisons approved.

Review changes


feat/storybook-client-side-navigation · a8cd6d57

@Robdel12 Robdel12 merged commit c178bf2 into main Jan 30, 2026
29 checks passed
@Robdel12 Robdel12 deleted the feat/storybook-client-side-navigation branch January 30, 2026 03:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant